// 实现这个项目的构建任务
// .gitignore 这个文件的作用就是告诉Git哪些文件不需要添加到版本管理中

const { src, dest, parallel, series, addListener, watch } = require('gulp')
// src 读取流  dest 写入流 parallel 并行 series 串行, watch监听

// 清空目录
const del = require('del')
// 自动执行插件 gulp-sass => plugins.sass 
const loadPlugins = require('gulp-load-plugins')
const plugins = loadPlugins()
// 创建服务器 browser-sync
const browserSync = require('browser-sync')
const bs = browserSync.create()

const cwd = process.cwd()
const path = require('path')
let config = {
    data: {},
    build: {
        src: 'src',
        dist: 'dist',
        temp: '.temp',
        public: 'public',
        paths: {
            styles: 'assets/styles/*.scss',
            scripts: 'assets/scripts/*.js',
            pages: '*.html',
            images: 'assets/images/**',
            fonts: 'assets/fonts/**'
        }
    }
}

try {
    const loadConfig = require(path.join(cwd, 'pages.config.js'))
    console.log(loadConfig)
    config = Object.assign({}, config, loadConfig)
} catch (e) { }

const style = () => {
    // base 保留目录结构
    return src(config.build.paths.styles, { base: config.build.src, cwd: config.build.src })
        // 完全展开的样式 expanded
        .pipe(plugins.sass())
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true })) // 以流的方式，提交浏览器
}

const script = () => {
    return src(config.build.paths.styles, { base: config.build.temp, cwd: config.build.src })
        // 完全展开的样式 expanded
        .pipe(plugins.babel({ presets: [require('@babel/preset-env')] }))
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true })) // 以流的方式，提交浏览器
}

const page = () => {
    // ** 表示任意目录下的html
    return src(config.build.paths.pages, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.swig({ data: config.data }))
        .pipe(dest(config.build.temp))
        .pipe(bs.reload({ stream: true })) // 以流的方式，提交浏览器
}

const image = () => {
    return src(config.build.paths.images, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.imagemin())
        .pipe(dest(config.build.dist))
}

const font = () => {
    return src(config.build.paths.fonts, { base: config.build.src, cwd: config.build.src })
        .pipe(plugins.imagemin())
        .pipe(dest(config.build.dist))
}

const extra = () => {
    return src('**', { base: config.build.public, cwd: config.build.public })
        .pipe(dest(config.build.dist))
}

const clean = () => {
    return del([config.build.temp, config.build.dist])
}

const useref = () => {
    return src(config.build.paths.pages, { base: config.build.temp, cwd: config.build.temp })
        .pipe(plugins.useref({ searchPath: [config.build.temp, '.'] }))
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({
            collapseWhitespace: true,
            minifyCSS: true,
            minifyJS: true
        })))
        .pipe(dest(config.build.dist))
}

const serve = () => {
    watch(config.build.paths.styles, { cwd: config.build.src }, style)
    watch(config.build.paths.scripts, { cwd: config.build.src }, style)
    watch(config.build.paths.pages, { cwd: config.build.src }, style)
    // browserSync的使用
    watch([
        config.build.paths.images,
        config.build.paths.fonts,
    ], { cwd: config.build.src }, bs.reload)

    watch('**', { cwd: config.build.public }, bs.reload)
    bs.init({
        notify: false,
        port: '3002',
        // files: 'dist/**', //监听diss文件  和.pipe(bs.reload({ stream: true }))效果一样
        server: {
            baseDir: [ config.build.src,  config.build.temp,  config.build.public], // 可以为数组或sting 数组顺序从前到后
            routes: {
                '/node_modules': 'node_modules' // 路由的映射
            }
        }
    })
}

// 开发阶段
const compile = parallel(style, script, page)
// 上线的任务
const build = series(clean, parallel(series(compile, useref), image, font, extra))

const start = series(compile, serve)

module.exports = {
    start,
    build,
    compile,
    clean,
    serve
}
